package com.sztx.pay.center.rpc.service;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.sztx.pay.center.common.util.Constance;
import com.sztx.pay.center.common.util.Constance.CallBackOrderState;
import com.sztx.pay.center.core.service.OrderMappingService;
import com.sztx.pay.center.core.service.bean.NotifyModel;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderB2cMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.OrderRechargeMysqlDAO;
import com.sztx.pay.center.dataaccess.dao.mysql.PayFlowMysqlDAO;
import com.sztx.pay.center.dataaccess.domain.OrderB2cDO;
import com.sztx.pay.center.dataaccess.domain.OrderRechargeDO;
import com.sztx.pay.center.dataaccess.domain.PayFlowDO;
import com.sztx.pay.center.rpc.api.domain.ReturnCallBackResult;
import com.sztx.pay.center.rpc.api.service.CallBackRpcService;
import com.sztx.se.common.exception.BusinessException;
import com.sztx.se.common.util.StringUtil;
import com.sztx.se.common.util.date.DateUtil;
import com.sztx.se.core.service.impl.BaseServiceImpl;
import com.sztx.se.rpc.dubbo.client.DubboClientFactory;
import com.sztx.trade.payment.gateway.common.trade.constant.TradeStatus;
import com.sztx.trade.payment.gateway.rpc.api.service.trade.ReqCallbackTrade;
import com.sztx.trade.payment.gateway.rpc.api.service.trade.RespCallBackTrade;
import com.sztx.trade.payment.gateway.rpc.api.service.trade.TradeRpcService;
@Service
public class CallBackRpcServiceImpl extends BaseServiceImpl implements CallBackRpcService{
	@Autowired
	private PayFlowMysqlDAO payFlowMysqlDAO;
	@Autowired
	OrderMappingService orderMappingService;
	@Autowired
	private OrderB2cMysqlDAO orderB2cMysqlDAO;
	@Autowired
	private OrderRechargeMysqlDAO orderRechargeMysqlDAO;
	@Autowired
	private DubboClientFactory dubboConsumerFactory;
	
	@Override
	public ReturnCallBackResult getReturnBackInfo(String orderId,Map<String, String> requestMap) {
		TradeRpcService tradeRpcService= dubboConsumerFactory.getDubboClient("gateWayTradeRpcService");
		ReqCallbackTrade request = new ReqCallbackTrade();
		request.setReqMap(requestMap);
		request.setTradeOrderId(orderId);
		RespCallBackTrade respCallBackTrade = tradeRpcService.callbackTrade(request);
		String tranOrderId = respCallBackTrade.getOrderId();
		String orderStatus = respCallBackTrade.getOrderStatus();
		String orderStatusDesc= respCallBackTrade.getOrderStatusDesc();
		CallBackOrderState callBackOrderState = null;
		int orderStatusI = TradeStatus.TS_UNKNOWN;
		if(!StringUtil.isBlank(orderStatus)){
			orderStatusI = Integer.parseInt(orderStatus);
		}
		switch (orderStatusI) {
		case TradeStatus.TS_SUCCEEDED:
			callBackOrderState = CallBackOrderState.SUCCESS;
			orderStatusDesc = "SUCCESS";
			break;
		case TradeStatus.TS_FAILED:
			callBackOrderState = CallBackOrderState.FAIL;
			orderStatusDesc = "FAIL";
			break;
		default:
			callBackOrderState = CallBackOrderState.EXCEPTION;
			orderStatusDesc = "EXCEPTION";
			break;
		}
		
		
		PayFlowDO payFlow = payFlowMysqlDAO.findById(tranOrderId);
		if (payFlow == null) {
			LOG.error("支付系统未查询到订单：" + tranOrderId);
			throw new BusinessException("请求异常,支付系统未查询到该订单!");
		}

		String mappingOrderId = payFlow.getTradeOrderNo();
		String tradeOrderId = orderMappingService.getTradeOrderId(mappingOrderId );
		
		String outOrderId = null;
		String returnUrl = null;
		OrderB2cDO orderB2cDO = orderB2cMysqlDAO.findById(tradeOrderId);
		
		if (orderB2cDO != null) {
			returnUrl = orderB2cDO.getReturnUrl();
			outOrderId = orderB2cDO.getOrderId();
		} else {
			OrderRechargeDO orderRechargeDO = orderRechargeMysqlDAO.findById(tradeOrderId);
			returnUrl = orderRechargeDO.getReturnUrl();
			outOrderId = orderRechargeDO.getOrderId();
		}
		
		NotifyModel notifyModel = new NotifyModel();
		notifyModel.setTradeOrderId(tradeOrderId);
		notifyModel.setOutOrderId(outOrderId);
		notifyModel.setTotalFee(0);
		notifyModel.setPayAmount(payFlow.getAmount().intValue());
		notifyModel.setPayTime(payFlow.getPayTime());
		notifyModel.setOrderState(callBackOrderState);//test
		notifyModel.setCharset(Constance.CHARSET);
		notifyModel.setSignType(Constance.SIGN_TYPE);
		notifyModel.setOrderDesc(orderStatusDesc);
		try {
			Map<String, String> parasMap = convertBean(notifyModel);
			String payTime = "";
			if(notifyModel.getPayTime() != null){
				payTime = DateUtil.formatDate(notifyModel.getPayTime(), "yyyyMMddHHmmss");	
			}
			parasMap = convertBean(notifyModel);
			parasMap.put("payTime", payTime);
			parasMap.put("orderState", String.valueOf(notifyModel.getOrderState().getCode()));
			String sign=createSign(parasMap,Constance.SIGN_KEY);
			parasMap.put("sign",sign);
			

			ReturnCallBackResult reslut = new ReturnCallBackResult();
			
			reslut.setParam(parasMap);
			reslut.setReturnUrl(returnUrl);
			return reslut;
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			throw new BusinessException("系统异常,生成验签信息失败");
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			throw new BusinessException("系统异常,生成验签信息失败");
		} catch (IntrospectionException e) {
			e.printStackTrace();
			throw new BusinessException("系统异常,生成验签信息失败");
		}
		
	}
	/**
	 * 对象转map
	 * @param bean
	 * @return
	 * @throws IntrospectionException
	 * @throws IllegalAccessException
	 * @throws InvocationTargetException
	 */
	public Map<String,String> convertBean(Object bean)
            throws IntrospectionException, IllegalAccessException, InvocationTargetException {
        Class<? extends Object> type = bean.getClass();
        Map<String,String> returnMap = new HashMap<String,String>();
        BeanInfo beanInfo = Introspector.getBeanInfo(type);

        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
        for (int i = 0; i< propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();
            if (!propertyName.equals("class")) {
                Method readMethod = descriptor.getReadMethod();
                Object result = readMethod.invoke(bean, new Object[0]);
                if (result != null) {
                    returnMap.put(propertyName, result.toString());
                } else {
                    returnMap.put(propertyName, "");
                }
            }
        }
        return returnMap;
    }
	/**
	 * 生成签名
	 * @param packageParams
	 * @param signKey
	 * @return
	 */
	public String createSign(Map<String, String> packageParams,
			String signKey) {
		SortedMap<String, String> sortedMap = new TreeMap<String, String>();
		sortedMap.putAll(packageParams);

		List<String> keys = new ArrayList<String>(packageParams.keySet());
		Collections.sort(keys);

		StringBuffer toSign = new StringBuffer();
		for (String key : keys) {
			String value = packageParams.get(key);
			if (null != value && !"".equals(value) && !"sign".equals(key) && !"key".equals(key)) {
				toSign.append(key + "=" + value + "&");
			}
		}
		toSign.append("key=" + signKey);
		String sign = DigestUtils.md5Hex(toSign.toString()).toUpperCase();
		return sign;
	}
}
